﻿using System;
using System.Collections.Generic;
using System.Configuration.Provider;
using System.Linq;
using System.Net;
using System.Text;
using System.Timers;

namespace Thor.Domain
{
    

    /// <summary>
    /// A base class for all calendar providers to inherit from.
    /// </summary>
    public abstract class CalendarProviderBase : ProviderBase, ICalendarProvider
    {
        /// <summary>
        /// Authenticates the specified credentials against the calendar provider.
        /// </summary>
        /// <param name="credential"></param>
        /// <param name="serviceUrl">Url to the service providing calendar data.</param>
        /// <returns></returns>
        public abstract AuthenticationResult Authenticate(NetworkCredential credential, string serviceUrl);

        /// <summary>
        /// Gets data for a specific calendar.
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public Calendar GetCalendar(CalendarRequest request)
        {
            if (!request.StartDate.HasValue)
                request.StartDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day);

            if (!request.EndDate.HasValue)
                request.EndDate = new DateTime(DateTime.Today.Year, DateTime.Today.Month, DateTime.Today.Day).AddHours(23).AddMinutes(59).AddSeconds(59);

            var calendar = OnGetCalendar(request);

            if (calendar != null)
            {
                calendar.CalendarEmail = request.CalendarId;
                calendar.Alias = request.Alias;
            }

            return calendar;
        }

        /// <summary>
        /// Gets data for a specific calendar
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        protected abstract Calendar OnGetCalendar(CalendarRequest request);

        /// <summary>
        /// Books an appointment.
        /// </summary>
        /// <param name="appointmentRequest"></param>
        public AppointmentResponse BookAppointment(AppointmentRequest appointmentRequest)
        {
            if (appointmentRequest.UseBookingAgent)
                return OnBookViaAgent(appointmentRequest);
            else
                return OnBookDirect(appointmentRequest);
        }

        /// <summary>
        /// Books an appointment directly.
        /// </summary>
        /// <param name="appointmentRequest"></param>
        /// <returns></returns>
        protected abstract AppointmentResponse OnBookDirect(AppointmentRequest appointmentRequest);

        /// <summary>
        /// Books an appointment via an agent.
        /// </summary>
        /// <param name="appointmentRequest"></param>
        /// <returns></returns>
        protected abstract AppointmentResponse OnBookViaAgent(AppointmentRequest appointmentRequest);

        /// <summary>
        /// Builds an email message body from an appointment request.
        /// </summary>
        /// <param name="appointmentRequest"></param>
        /// <returns></returns>
        protected string GetBodyFromRequest(AppointmentRequest appointmentRequest)
        {
            StringBuilder body = new StringBuilder();
            body.AppendLine(string.Format("Meeting Resource: {0}", appointmentRequest.CalendarId));
            body.AppendLine(string.Format("Meeting Subject: {0}", appointmentRequest.Subject));
            body.AppendLine(string.Format("Start Time: {0}", appointmentRequest.StartTime.ToString()));
            body.AppendLine(string.Format("End Time: {0}", appointmentRequest.EndTime.ToString()));
            return body.ToString();
        }

        /// <summary>
        /// Determines if the calendar is busy.
        /// </summary>
        /// <param name="appointmentRequest"></param>
        /// <returns></returns>
        protected bool IsBusy(AppointmentRequest appointmentRequest)
        {
            CalendarRequest request = new CalendarRequest()
            {
                Credential = appointmentRequest.Credential,
                ServiceUrl = appointmentRequest.ServiceUrl,
                CalendarId = appointmentRequest.CalendarId,
                StartDate = appointmentRequest.StartTime,
                EndDate = appointmentRequest.EndTime
            };

            var cal = this.GetCalendar(request);

            if (cal != null && cal.Appointments != null && cal.Appointments.Count > 0)
                return true;
            else
                return false;
        }
    }
}